#include "GameLoop.h"


#include <SDL.h>
#include <iostream>

#include "main/Globals.h"
#include "main/MainConstants.h"
#include "utils/Error.h"
#include "utils/Timer.h"
#include <graphic\DrawManager.h>


GameLoop::GameLoop() : run(true), isUpdating(false) {}

void GameLoop::loop() {
	while(run) {
        // Begin of frame tick
        Globals::gTimer.tick();

        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                run = false;
                break;
            } else if (event.type == SDL_MOUSEMOTION) {
                Globals::gMouseState.handleMouseMotionEvent(event.motion);
            } else if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) {
                Globals::gKeyboardState.handleKeyboardEvent(event.key);
            }
        }

        // Update mouse buttons state
        // (keyboard state is updated automatically)
        Globals::gMouseState.updateButtonsState();

		//Clear screen
		SDL_SetRenderDrawColor(Globals::gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
		SDL_RenderClear(Globals::gRenderer);

        // Invoke all the updateables here
		isUpdating = true;
        for(std::vector<Iupdateable*>::iterator it = updateables.begin(); it != updateables.end(); ++it) {
			(*it)->update();
			if(!queuedDeletes.empty()) { 
				break;
			}
        }
		isUpdating = false;

		// Process pending deletes
		for(std::vector<Iupdateable*>::iterator it = queuedDeletes.begin(); it != queuedDeletes.end(); it++) {
			updateables.erase(std::find(updateables.begin(), updateables.end(), *it));
		}
		queuedDeletes.clear();

		// Proces pending adds
		updateables.insert(updateables.end(), queuedInserts.begin(), queuedInserts.end());
		queuedInserts.clear();
		
		// Draw the debug collisions (ifdefed)
		SDL_SetRenderDrawColor(Globals::gRenderer, 0x00, 0x00, 0x00, 0x00 );
		Globals::gCollisionManager->drawDebug();

		// Draw the drawables
		Globals::gDrawManager->drawAll();

		//Update screen
		SDL_RenderPresent(Globals::gRenderer);

        // Clear input events (mouse & keyboards)
		Globals::gKeyboardState.clearKeyEvents();
        Globals::gMouseState.clearMouseEvents();

        // End of frame tick
        // Ensure current frame takes at least
        // MS_PER_FRAME
        Globals::gTimer.tick();           
        double elapsedTime = Globals::gTimer.deltaTime();
        //std::cout << "Elapsed = " << elapsedTime << std::endl;
        while (elapsedTime < MS_PER_FRAME_DOUBLE) {
            Globals::gTimer.tick();
            elapsedTime += Globals::gTimer.deltaTime();
        }  
	}
}

void GameLoop::stop() {
	run = false;
}

void GameLoop::updateMe(Iupdateable* updateable) {
	if (isUpdating) {
		queuedInserts.push_back(updateable);
	} else {
		updateables.push_back(updateable);
	}
}

void GameLoop::removeMe(Iupdateable* updateable) {
	queuedDeletes.push_back(updateable);
	/*
	if (isUpdating) {
		
	} else {
		updateables.erase(std::find(updateables.begin(), updateables.end(), updateable));
	}*/
}
